package heap

import "jvm/nzpJvm/classfile"

// 一个方法的符号引用
type MethodRef struct {
	MemberRef
	method *Method
}

// 新建一个方法的符号引用
func newMethodRef(pool *ConstantPool, info *classfile.ConstantMethodrefInfo) Constant {
	methodRef := &MethodRef{}
	methodRef.cp = pool
	methodRef.copyMemberRefInfo(&info.ConstantMemberRefInfo)
	return methodRef
}

// 根据方法的符号引用获取直接引用
func (self *MethodRef) ResolveMethod() *Method {
	// 如果还没有解析过，就解析
	if self.method == nil {
		self.ResolveMethodRef()
	}
	return self.method
}

// 将方法的符号引用转换为直接引用
func (self *MethodRef) ResolveMethodRef() {
	// 当前类，也就是触发解析的类
	currentClass := self.cp.class
	// 目标类，也就是定义这个方法的类
	class := self.ResolveClass()
	if class.IsInterface() {
		// 不考虑接口中的静态方法和default方法，不支持
		panic("java.lang.IncompatibleClassChangeError")
	}
	method := lookupMethod(class, self.name, self.descriptor)
	if method == nil {
		panic("java.lang.NoSuchMethodError")
	}

	// 判断当前类是否可以访问到这个方法
	if !method.isAccessibleTo(currentClass) {
		panic("java.lang.IllegalAccessError")
	}
	self.method = method
}

// 从类中查找方法
func lookupMethod(class *Class, name string, descriptor string) *Method {
	// 从当前类以及所有的父类中查找这个方法
	method := LookupMethodInClass(class, name, descriptor)
	// 当前类以及所有的父类中都没有找到这个方法，则查找所有的父接口
	if method == nil {
		method = LookupMethodInInterface(class.interfaces, name, descriptor)
	}
	return method
}

